Hoja de trabajo 03 - Regresión Lineal

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(knitr)
library(ggplot2)
library(cluster)
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
require(caret)
## Loading required package: caret
## Loading required package: lattice
library(corrplot)
## corrplot 0.92 loaded
library(Metrics)
## 
## Attaching package: 'Metrics'
## The following objects are masked from 'package:caret':
## 
##     precision, recall
library(hopkins)
library(e1071)
library(mclust)
## Package 'mclust' version 6.0.0
## Type 'citation("mclust")' for citing this R package in publications.
library(fpc) 
library(NbClust) 
library(GGally)
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
library(FeatureImpCluster)
## Loading required package: data.table
## 
## Attaching package: 'data.table'
## The following objects are masked from 'package:dplyr':
## 
##     between, first, last
library(pheatmap)
library(ggplot2)
options(dplyr.summarise.inform = FALSE)
data <- read.csv("train.csv")

Análisis Exploratorio

¿Cuál es la Zona más cara?

grouped_data <- data %>% group_by(MSZoning)
agg_tbl <- grouped_data %>% summarise(median(SalePrice))
grouped_dataset <- as.data.frame(agg_tbl)
colnames(grouped_dataset)[colnames(grouped_dataset) == "MSZoning"] ="Zona"
colnames(grouped_dataset)[colnames(grouped_dataset) == "median(SalePrice)"] ="Promedio de Precio (USD)"
grouped_dataset <- grouped_dataset[order(grouped_dataset$`Promedio de Precio (USD)`, decreasing = TRUE), ]
kable(grouped_dataset, caption = "Promedio de ventas por cada zona")
Promedio de ventas por cada zona
Zona Promedio de Precio (USD)
2 FV 205950
4 RL 174000
3 RH 136500
5 RM 120500
1 C (all) 74700

Un 50% de las casas en la zona Floating Village Residential se venden por arriba de los 205940.00 USD. Posteriormente sigue Residential Low Density.

¿En qué vecindario se ubican las casas con mayor área en su terreno?

grouped_area_data <- data %>% group_by(Neighborhood)
area_with_median <- grouped_area_data %>% summarise(median(LotArea))
grouped_dataset_lot <- as.data.frame(area_with_median)
colnames(grouped_dataset_lot)[colnames(grouped_dataset_lot) == "Neighborhood"] ="Vecindario"
colnames(grouped_dataset_lot)[colnames(grouped_dataset_lot) == "median(LotArea)"] ="Area del terreno ft^2"
grouped_dataset_lot <- grouped_dataset_lot[order(grouped_dataset_lot$`Area del terreno ft^2`, decreasing = TRUE), ]
kable(grouped_dataset_lot[0:5,], caption = "Mediana de area por cada vecindario")
Mediana de area por cada vecindario
Vecindario Area del terreno ft^2
5 ClearCr 17575.0
24 Timber 12781.5
16 NoRidge 12090.0
17 NridgHt 11694.0
7 Crawfor 11500.0
ggplot(grouped_dataset_lot[0:5,], aes(x=Vecindario, y=`Area del terreno ft^2`)) +
geom_bar(stat="identity", fill="steelblue") 

La información nos demuestra que Clear Creek es el vecindario que tiene los terrenos con mayor área. Un 50% de los terrenos tiene un área mayor a 17575.0 pies cuadrados.

¿En qué año hubo más remodelaciones?

data_with_remodelation <- data[data$YearBuilt != data$YearRemodAdd,]

En el dataset hay 696 registros de casas que fueron remodeladas. A continuación agrupamos por año la cantidad de remodelaciones.

grouped_remodelation_data <- data_with_remodelation %>% group_by(YearRemodAdd)
year_with_count <- grouped_remodelation_data %>% summarise(total_count=n(),
            .groups = 'drop')

grouped_remodelation <- as.data.frame(year_with_count)
colnames(grouped_remodelation)[colnames(grouped_remodelation) == "YearRemoAdd"] ="Año"
colnames(grouped_remodelation)[colnames(grouped_remodelation) == "total_count"] ="Cantidad de casas remodeladas"
grouped_remodelation <- grouped_remodelation[order(grouped_remodelation$`Cantidad de casas remodeladas`, decreasing = TRUE), ]
kable(grouped_remodelation[0:5,], caption = "Numero de casas Remodeladas por año")
Numero de casas Remodeladas por año
YearRemodAdd Cantidad de casas remodeladas
1 1950 166
44 2006 51
45 2007 42
43 2005 40
38 2000 33

Los 5 años con más casas remodeladas son 1950, 2006, 2007, 2005 y 2000 respectivamente. Es importante notar que en 1950 hay mucha más diferencia que con los demás años.

most_remodelated_zone_1950 <- tail(names(sort(table(data_with_remodelation[data_with_remodelation$YearRemodAdd == "1950",]$MSZoning))), 1)

most_remodelated_zone_2006 <- tail(names(sort(table(data_with_remodelation[data_with_remodelation$YearRemodAdd == "2006",]$MSZoning))), 1)

most_remodelated_zone_2007 <- tail(names(sort(table(data_with_remodelation[data_with_remodelation$YearRemodAdd == "2007",]$MSZoning))), 1)

La mayoría de las remodelaciones pertenecen a la zona RL - Residencial de baja densidad.

¿Cuáles son los materiales más utilizados para la fundación de las casas?

grouped_foundation_data <- data %>% group_by(Foundation)
foundation_with_count <- grouped_foundation_data %>% summarise(total_count=n(),
            .groups = 'drop')

grouped_foundation <- as.data.frame(foundation_with_count)
colnames(grouped_foundation)[colnames(grouped_foundation) == "Foundation"] ="Material para la base"
colnames(grouped_foundation)[colnames(grouped_foundation) == "total_count"] ="Cantidad de casas"
grouped_foundation <- grouped_foundation[order(grouped_foundation$`Cantidad de casas`, decreasing = TRUE), ]
kable(grouped_foundation[0:5,], caption = "Numero de casas por cada material de base")
Numero de casas por cada material de base
Material para la base Cantidad de casas
3 PConc 647
2 CBlock 634
1 BrkTil 146
4 Slab 24
5 Stone 6

La mayoría de casas están hechas de concreto. Puede ser que un tipo menos común, pero más caro, como el ladrillo signifique un precio más alto.

¿Qué tipos de casa son más comunes?

grouped_type_data <- data %>% group_by(BldgType)
type_count <- grouped_type_data %>% summarise(total_count=n(), .groups = 'drop')

grouped_type <- as.data.frame(type_count)
colnames(grouped_type)[colnames(grouped_type) == "BldgType"] ="Tipo de casa"
colnames(grouped_type)[colnames(grouped_type) == "total_count"] ="Cantidad"
grouped_type <- grouped_type[order(grouped_type$`Cantidad`, decreasing = TRUE), ]
kable(grouped_type[0:5,], caption = "Conteo de tipo de casas")
Conteo de tipo de casas
Tipo de casa Cantidad
1 1Fam 1220
5 TwnhsE 114
3 Duplex 52
4 Twnhs 43
2 2fmCon 31

¿Cómo varia el precio de las casas según el vecindario en que se encuentran?

grouped_data <- data %>% group_by(Neighborhood)
agg_tbl <- grouped_data %>% summarise(mean(SalePrice))
grouped_dataset <- as.data.frame(agg_tbl)
colnames(grouped_dataset)[colnames(grouped_dataset) == "Neighborhood"] ="Vecindario"
colnames(grouped_dataset)[colnames(grouped_dataset) == "mean(SalePrice)"] ="Promedio de Precio (USD)"
grouped_dataset <- grouped_dataset[order(grouped_dataset$`Promedio de Precio (USD)`, decreasing = TRUE), ]
kable(grouped_dataset, caption = "Promedio de ventas por cada vecindario")
Promedio de ventas por cada vecindario
Vecindario Promedio de Precio (USD)
16 NoRidge 335295.32
17 NridgHt 316270.62
23 StoneBr 310499.00
24 Timber 242247.45
25 Veenker 238772.73
22 Somerst 225379.84
5 ClearCr 212565.43
7 Crawfor 210624.73
6 CollgCr 197965.77
1 Blmngtn 194870.88
9 Gilbert 192854.51
15 NWAmes 189050.07
21 SawyerW 186555.80
12 Mitchel 156270.12
13 NAmes 145847.08
14 NPkVill 142694.44
19 SWISU 142591.36
2 Blueste 137500.00
20 Sawyer 136793.14
18 OldTown 128225.30
8 Edwards 128219.70
4 BrkSide 124834.05
3 BrDale 104493.75
10 IDOTRR 100123.78
11 MeadowV 98576.47

¿Que proporción de casas se encuentra en cada zona?

zone_counts <- data %>% count(MSZoning) %>% mutate(Proporcion = prop.table(n) * 100) %>% 
rename(Zona = MSZoning, Cantidad = n) %>% mutate(Proporcion = paste0(round(Proporcion, 2), "%")) %>%
arrange(desc(Proporcion))
kable(zone_counts, caption = "Proporción de casas por zona")
Proporción de casas por zona
Zona Cantidad Proporcion
RL 1151 78.84%
FV 65 4.45%
RM 218 14.93%
RH 16 1.1%
C (all) 10 0.68%

¿Cuáles son las características más comunes de las casas que se venden por encima del precio medio?

price_mean_up <- mean(data$SalePrice)
houses_mean_above <- subset(data, SalePrice > price_mean_up)
ggplot(data = houses_mean_above, aes(x = MSZoning)) +geom_bar()

ggplot(data = houses_mean_above, aes(x = BldgType)) +geom_bar()

ggplot(data = houses_mean_above, aes(x = HouseStyle)) +geom_bar()

ggplot(data = houses_mean_above, aes(x = GarageType)) +geom_bar()

Las características más comunes son las siguientes: 1) Zona donda se ubica las casas: RL (Casa residencial de baja densidad) 2) Tipo de vivienda: 1Fam (Unifamiliar) 3) Estilo de la casa: 1Story (Un nivel) 4) Tipo de Garaje: Attchd (Adjuntada a la casa)

¿Cuántas casas tienen piscina o garaje? ¿Como se relacionan estas características con el precio de venta?

print("Counting Pools And Garages")
## [1] "Counting Pools And Garages"
nrow(data) - table(data$PoolArea > 0)
## 
## FALSE  TRUE 
##     7  1453
nrow(data) - nrow(data[data$GarageType=="NA",])
## [1] 1379
print("")
## [1] ""
print("Relation with the seal price")
## [1] "Relation with the seal price"
tapply(data$SalePrice, data$PoolQC > 0, mean)
##     TRUE 
## 288138.6
tapply(data$SalePrice, data$GarageType=="NA", mean)
##    FALSE 
## 185479.5

1453 casas tienen psicina 1379 casas cuentan con garaje

Como se puede ver si influyen la relación con el precio, las psicinas suelen elevar el precio de las casas

¿Cómo se distribuyen las ventas de casas a lo largo del tiempo entre los diferentes periodos?

ggplot(data = data, aes(x = factor(YrSold))) +
  geom_bar(fill = "green") +
  ggtitle("Ventas de casas por año") +
  xlab("Año") +
  ylab("Cantidad de ventas")

ggplot(data = data, aes(x = YrSold, y = SalePrice)) +
  geom_line(color = "green") +
  ggtitle("Tendencia del precio de venta") +
  xlab("Año") +
  ylab("Precio de venta promedio")

Como se puede ver en las dos gráficas presentadas desde el año 2006 al 2009 existio una tendencia donde subía y bajan las ventas de las casas. Pero desde 2010 este fue en bajando.

Preprocesamiento de datos

columns_used <- c()
neighborhoodNames <- c("NoRidge", "NridgHt", "StoneBr", "Timber", "Veenker", "Somerst", "ClearCr", "Crawfor", "CollgCr", "Blmngtn", "Gilbert", "NWAmes", "SawyerW", "Mitchel", "NAmes", "NPkVill", "SWISU", "Blueste", "Sawyer", "OldTown", "Edwards", "BrkSide", "BrDale", "IDOTRR", "MeadowV")

for(n in 1:length(neighborhoodNames)) {
  # Variable minuscula para nuestro uso.
  data$neighborhood[data$Neighborhood == neighborhoodNames[n]] <- n
}
columns_used <- append(columns_used, "neighborhood")

hs <- c("1Story", "2Story", "1.5Fin",   "SLvl", "SFoyer")

for(n in 1:length(hs)) {
  # Variable minuscula para nuestro uso.
  data$houseStyle[data$HouseStyle == hs[n]] <- n
}
columns_used <- append(columns_used, "houseStyle")

 data$houseZone[data$MSZoning == "A"] <- 1
 data$houseZone[data$MSZoning == "C"] <- 2
 data$houseZone[data$MSZoning == "FV"] <- 3
 data$houseZone[data$MSZoning == "I"] <- 4
 data$houseZone[data$MSZoning == "RH"] <- 5
 data$houseZone[data$MSZoning == "RL"] <- 6
 data$houseZone[data$MSZoning == "RP"] <- 7
 data$houseZone[data$MSZoning == "RM"] <- 8
 columns_used <- append(columns_used, "houseZone")

data$houseUtilities[data$Utilities == "AllPub"] <- 1
data$houseUtilities[data$Utilities == "NoSewr"] <- 2
data$houseUtilities[data$Utilities == "NoSeWa"] <- 3
data$houseUtilities[data$Utilities == "ELO"] <- 4
columns_used <- append(columns_used, "houseUtilities")

data$roadAccess[data$Condition1 == "Artery"] <- 1
data$roadAccess[data$Condition1 == "Feedr"] <- 2
data$roadAccess[data$Condition1 == "Norm"] <- 3
data$roadAccess[data$Condition1 == "RRNn"] <- 4
data$roadAccess[data$Condition1 == "RRAn"] <- 5
data$roadAccess[data$Condition1 == "PosN"] <- 6
data$roadAccess[data$Condition1 == "PosA"] <- 7
data$roadAccess[data$Condition1 == "RRNe"] <- 8
data$roadAccess[data$Condition1 == "RRAe"] <- 9
columns_used <- append(columns_used, "roadAccess")

data$remodelated[data$YearBuilt != data$YearRemodAdd] <- 1
data$remodelated[data$YearBuilt == data$YearRemodAdd] <- 0
columns_used <- append(columns_used, "remodelated")

data$roofStyle[data$RoofStyle == "Flat"]  <- 1
data$roofStyle[data$RoofStyle == "Gable"]  <- 2
data$roofStyle[data$RoofStyle == "Gambrel"]  <- 3
data$roofStyle[data$RoofStyle == "Hip"]  <- 4
data$roofStyle[data$RoofStyle == "Mansard"]  <- 5
data$roofStyle[data$RoofStyle == "Shed"]  <- 6
columns_used <- append(columns_used, "roofStyle")

data$roofMaterial[data$RoofMatl == "ClyTile"] <- 1
data$roofMaterial[data$RoofMatl == "CompShg"] <- 2
data$roofMaterial[data$RoofMatl == "Membran"] <- 3
data$roofMaterial[data$RoofMatl == "Metal"] <- 4
data$roofMaterial[data$RoofMatl == "Roll"] <- 5
data$roofMaterial[data$RoofMatl == "Tar&Grv"] <- 6
data$roofMaterial[data$RoofMatl == "WdShake"] <- 7
data$roofMaterial[data$RoofMatl == "WdShngl"] <- 8
columns_used <- append(columns_used, "roofMaterial")

data$overallQuality <- data$OverallQual
columns_used <- append(columns_used, "overallQuality")

data$overallCondition <- data$OverallCond
columns_used <- append(columns_used, "overallCondition")


data$exteriorCondition[data$ExterCond == "Po"] <- 1
data$exteriorCondition[data$ExterCond == "Fa"] <- 2
data$exteriorCondition[data$ExterCond == "TA"] <- 3
data$exteriorCondition[data$ExterCond == "Gd"] <- 4
data$exteriorCondition[data$ExterCond == "Ex"] <- 5
columns_used <- append(columns_used, "exteriorCondition")

data$foundationMaterial[data$Foundation == "BrkTil"] <- 1
data$foundationMaterial[data$Foundation == "CBlock"] <- 2
data$foundationMaterial[data$Foundation == "PConc"] <- 3
data$foundationMaterial[data$Foundation == "Slab"] <- 4
data$foundationMaterial[data$Foundation == "Stone"] <- 5
data$foundationMaterial[data$Foundation == "Wood"] <- 6
columns_used <- append(columns_used, "foundationMaterial")

data$basement[is.na(data$BsmtQual)] <- 0
data$basement[!is.na(data$BsmtQual)] <- 1
columns_used <- append(columns_used, "basement")

data$basementCondition[data$BsmtCond == "Ex"] <- 3
data$basementCondition[data$BsmtCond == "Gd"] <- 2
data$basementCondition[data$BsmtCond != "Ex"] <- 1
data$basementCondition[data$BsmtCond != "Gd"] <- 1
data$basementCondition[is.na(data$BsmtCond)] <- 0
columns_used <- append(columns_used, "basementCondition")

data$fireplace[is.na(data$FireplaceQu)] <- 0
data$fireplace[!is.na(data$FireplaceQu)] <- 1
columns_used <- append(columns_used, "fireplace")

data$garageArea <- data$GarageArea
columns_used <- append(columns_used, "garageArea")

data$pool[is.na(data$PoolQC)] <- 0
data$pool[!is.na(data$PoolQC)] <- 1
columns_used <- append(columns_used, "pool")

data$additionalFeature[is.na(data$MiscFeature)] <- 0
data$additionalFeature[!is.na(data$MiscFeature)] <- 1
columns_used <- append(columns_used, "additionalFeature")

data$livingArea <- data$GrLivArea
columns_used <- append(columns_used, "livingArea")

data$yearBuilt <- data$YearBuilt
columns_used <- append(columns_used, "yearBuilt")


data$salePrice <- data$SalePrice
columns_used <- append(columns_used, "salePrice")

tv <- c("WD", "Oth", "New", "ConLw", "ConLI", "ConLD", "Con", "CWD", "COD")

for(n in 1:length(tv)) {
  # Variable minuscula para nuestro uso.
  data$saleType[data$SaleType == tv[n]] <- n
}
columns_used <- append(columns_used, "saleType")

msz <- c("FV", "RL", "RH", "RM" , "C (all)")

for(n in 1:length(msz)) {
  # Variable minuscula para nuestro uso.
  data$mSZoning[data$MSZoning == msz[n]] <- n
}
columns_used <- append(columns_used, "mSZoning")

Borrando valores inneceesarios

cleanData <- subset(data, select = columns_used)

Dividiendo los datos en entrenamiento y prueba

Dividimos el test de datos en un 75% para entrenamiento y un 25% para pruebas. Utilizamos el metodo de bootstraping porque nos asegura que la distribución de la data toma en cuenta la población total. Es decir, no tendremos un sesgo genrado por cómo la información está organizada.

set.seed(5)
expectedResult <- cleanData$salePrice
partition <- createDataPartition(y=expectedResult,
                                 p=.75,
                                 list=F)

trainingSet <- cleanData[partition,]
testingSet <- cleanData[-partition,]

Ingeniería de los Datos

Visualizamos la matriz de correlación para ver tendencias en la data.

correlations <- cor(cleanData[,c("neighborhood", "yearBuilt", "overallCondition", "overallQuality", "houseZone", "houseUtilities")], use="pairwise.complete.obs")
corrplot(correlations, method="circle", type="lower",  sig.level = 0.01, insig = "blank")

De esta figura obtenemos las siguientes conclusiones: - El año en el que se hizo la casa está correlacionado con el vecindario en el que se encuentra. - La condición de la casa tienen una correlación ligeramente negativa. Puede ser que mientras el año es menor, la condición actual reduce. - La zona donde se encuentra la casa también está ligeramente relacionada a la calidad de los materiales.

Continuamos con un segundo diagrama

correlations <- cor(cleanData[,c("neighborhood", "yearBuilt", "overallCondition", "overallQuality", "pool", "fireplace", "foundationMaterial", "exteriorCondition", "additionalFeature", "livingArea" )], use="pairwise.complete.obs")
corrplot(correlations, method="circle", type="lower",  sig.level = 0.01, insig = "blank")

Este diagrama nos da otra información de las variables: - Mientras mejor sea la condición del exterior, mejor es la condición en general de la casa. - la pisicna está ligeramente correlacionada con tener una fogata y con la condición del exterior de la casa. - El material usado para la base de la casa está relacionado con el año de construcción de esta. - El area de vivienda de la casa incrementa conforme la calidad de la construcción lo hace. - Una área de vivienda mayor permite tener más comodidades, como fogata o una piscina.

Si hacemos una gráfica de puntos tomando en cuenta algunas variables importantes podemos obtener más información:

pairs(~yearBuilt+overallQuality+overallCondition+livingArea,data=cleanData,
   main="Matriz de correlación")

- la calidad de las casas ha mejorado con el paso de los años. - El área de vivienda aumenta ligeramente con el paso del tiempo.

Tomando este análisis en cuenta, se utilizarán las siguientes variables como candidatas a mejores predicciones: - yearBuilt - el año de construcción tiene una alta influencia en la calidad de la casa, vecindario donde se encuentra, condición actual y área de vivienda. - livingArea - el area de vivienda es un factor imporante porque indica cuánto espacio puede ser aprovechado en la casa. No es la misma área que necesita una familia de 2 personas a una de 5. Además, un área mayor permite tener comodidades como piscina o fogata. - overallQuality - La calidad de la casa también es importante para el precio. Esto nos indica que el material usado es resistente. - overallCondition - La condición actual de la casa da una mejor impresión al mostrarla a posibles clientes. - pool - Una piscina aumenta el precio dado que el cliente debe tener presupuesto para mantenerla. - fireplace - en Iowa (lugar del dataset) hay inviernos con nieve, los clientes agradecerán esta comodidad

Asegurando resultados consistentes

set.seed(5)

Modelo univariable

Modelo multivariable

Utilizamos todas las variables como una primera aproximación.

allVariablesModel <- lm(salePrice ~ ., data=trainingSet)
summary(allVariablesModel)
## 
## Call:
## lm(formula = salePrice ~ ., data = trainingSet)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -244657  -18333   -2015   15695  203644 
## 
## Coefficients: (2 not defined because of singularities)
##                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        -5.440e+05  1.261e+05  -4.315 1.75e-05 ***
## neighborhood       -2.628e+03  2.782e+02  -9.449  < 2e-16 ***
## houseStyle         -2.144e+03  1.088e+03  -1.971 0.048994 *  
## houseZone           7.459e+03  2.336e+03   3.193 0.001449 ** 
## houseUtilities             NA         NA      NA       NA    
## roadAccess         -1.170e+03  1.185e+03  -0.987 0.323691    
## remodelated         7.964e+03  2.297e+03   3.467 0.000548 ***
## roofStyle           6.302e+03  1.252e+03   5.034 5.65e-07 ***
## roofMaterial        2.306e+02  1.878e+03   0.123 0.902286    
## overallQuality      1.594e+04  1.275e+03  12.501  < 2e-16 ***
## overallCondition    4.513e+03  1.112e+03   4.060 5.26e-05 ***
## exteriorCondition  -1.826e+03  3.056e+03  -0.597 0.550408    
## foundationMaterial  1.462e+03  2.112e+03   0.692 0.489044    
## basement            1.104e+04  6.783e+03   1.628 0.103876    
## basementCondition          NA         NA      NA       NA    
## fireplace           6.022e+03  2.403e+03   2.506 0.012351 *  
## garageArea          5.114e+01  6.185e+00   8.269 4.06e-16 ***
## pool                1.218e+05  1.916e+04   6.355 3.10e-10 ***
## additionalFeature   1.013e+03  5.901e+03   0.172 0.863726    
## livingArea          5.190e+01  2.877e+00  18.037  < 2e-16 ***
## yearBuilt           2.454e+02  6.453e+01   3.802 0.000152 ***
## saleType            4.877e+02  6.355e+02   0.767 0.442992    
## mSZoning           -9.137e+03  3.183e+03  -2.870 0.004182 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 32540 on 1046 degrees of freedom
##   (30 observations deleted due to missingness)
## Multiple R-squared:  0.8264, Adjusted R-squared:  0.8231 
## F-statistic:   249 on 20 and 1046 DF,  p-value: < 2.2e-16

El valor de R cuadrado con este modelo es de 0.8231. Un valor arriba de 0.7 es considerado bueno para problemas de correlación. (Fernando, 2021) https://www.investopedia.com/terms/r/r-squared.asp#:~:text=In%20finance%2C%20an%20R%2DSquared,depend%20on%20the%20specific%20analysis. AGREGAR REFERERNCIAS

Prediciendo valores con este modelo

prediction <- predict(allVariablesModel, testingSet, type="response")
## Warning in predict.lm(allVariablesModel, testingSet, type = "response"):
## prediction from a rank-deficient fit may be misleading
model_output <- cbind(testingSet, prediction)

Observando primeros valores de la predicción

head(model_output[,c("salePrice", "prediction")])
##    salePrice prediction
## 1     208500   216973.9
## 4     140000   214242.5
## 5     250000   299280.3
## 6     143000   159179.9
## 8     200000   224751.9
## 15    157000   160281.3

Representando gráficamente el modelo

plot(allVariablesModel$fitted.values, allVariablesModel$residuals, xlab="Fitted",ylab="Residuals")

Estos residuales nos indican que el modelo no es del todo lineal. La gráfica no presenta los valores distribuídos aleatoriamente de manera horizontal centrados en y=0. Sin embargo, tampoco está del todo mal si consideramos el valor de R cuadrado.

Análisis del RMSE

complete_predicted <- na.omit(model_output)
rmseAllVariables <- rmse(complete_predicted$salePrice,complete_predicted$prediction)

Ahora el valor del RMSE es 4.9481264^{4}

Representando gráficamente el modelo

Clustering

Agrupamiento de las columnas más importantes

# Definir las columnas más importantes
important_cols <- c("YrSold", "SalePrice", "YearBuilt", "YearRemodAdd", "PoolArea", "GarageArea", "OverallQual", "OverallCond", "LotFrontage", "LotArea", "GarageCars")
# Normalizar variables numericas
cols_num_norm <- data[,important_cols] <- mutate_if(data[,important_cols], is.numeric, scale)

Resumen de las columnas a utilizar para llevar a cabo el clustering

print(summary(data[,important_cols]))
##       YrSold.V1          SalePrice.V1        YearBuilt.V1    
##  Min.   :-1.3671863   Min.   :-1.838074   Min.   :-3.286697  
##  1st Qu.:-0.6142282   1st Qu.:-0.641296   1st Qu.:-0.571727  
##  Median : 0.1387300   Median :-0.225587   Median : 0.057352  
##  Mean   : 0.0000000   Mean   : 0.000000   Mean   : 0.000000  
##  3rd Qu.: 0.8916881   3rd Qu.: 0.416387   3rd Qu.: 0.951306  
##  Max.   : 1.6446462   Max.   : 7.226343   Max.   : 1.282400  
##                                                              
##    YearRemodAdd.V1        PoolArea.V1        GarageArea.V1   
##  Min.   :-1.6887898   Min.   :-0.068668   Min.   :-2.212205  
##  1st Qu.:-0.8653621   1st Qu.:-0.068668   1st Qu.:-0.647694  
##  Median : 0.4424348   Median :-0.068668   Median : 0.032833  
##  Mean   : 0.0000000   Mean   : 0.000000   Mean   : 0.000000  
##  3rd Qu.: 0.9268040   3rd Qu.:-0.068668   3rd Qu.: 0.481841  
##  Max.   : 1.2174256   Max.   :18.299910   Max.   : 4.420012  
##                                                              
##    OverallQual.V1      OverallCond.V1      LotFrontage.V1       LotArea.V1     
##  Min.   :-3.687150   Min.   :-4.111561   Min.   :-2.01978   Min.   :-0.923413  
##  1st Qu.:-0.794879   1st Qu.:-0.517023   1st Qu.:-0.45502   1st Qu.:-0.296889  
##  Median :-0.071812   Median :-0.517023   Median :-0.04324   Median :-0.104028  
##  Mean   : 0.000000   Mean   : 0.000000   Mean   : 0.00000   Mean   : 0.000000  
##  3rd Qu.: 0.651256   3rd Qu.: 0.381612   3rd Qu.: 0.40972   3rd Qu.: 0.108671  
##  Max.   : 2.820459   Max.   : 3.077516   Max.   :10.00422   Max.   :20.511245  
##                                          NA's   :259                           
##     GarageCars.V1    
##  Min.   :-2.3646297  
##  1st Qu.:-1.0265059  
##  Median : 0.3116179  
##  Mean   : 0.0000000  
##  3rd Qu.: 0.3116179  
##  Max.   : 2.9878655  
## 

Hopkins

set.seed(123)
hopkins(data[, important_cols], m=1400)
## Warning in runif(m, min = colmin[i], max = colmax[i]): NAs produced
## [1] 0.9999868

El resultado es de 0.9999868, el cual indica una tendencia a clustering alta ya que es un valor cerca a 1.

Evaluación Visual de Tendencia de la data (VAT)

data_dist <- dist(data[, important_cols])
fviz_dist(data_dist, show_labels=F)

Determinar numero optimo de clusters

cols_num_norm_w <- na.omit(cols_num_norm)
fviz_nbclust(cols_num_norm_w, kmeans, method = "gap")
## Warning: did not converge in 10 iterations

## Warning: did not converge in 10 iterations

#fviz_nbclust(cols_num_norm_ww, kmeans, method = "silhouette")

El numero optimo de clusters es 4

number_clusters <- 4

K-Means para clustering

km <- kmeans(cols_num_norm_w, centers = number_clusters, iter.max = 100)
km$size
## [1] 167 375 332 327
fviz_cluster(km, cols_num_norm_w)

Clustering Jerarquico

hc<-hclust(data_dist, method = "ward.D2")
plot(hc, cex=0.5, axes=FALSE)
rect.hclust(hc,k=number_clusters)